wgl: Prevent null pointer reference.
[mesa.git] / src / gallium / state_trackers / wgl / shared / stw_context.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <windows.h>
29
30 #include "main/mtypes.h"
31 #include "main/context.h"
32 #include "pipe/p_compiler.h"
33 #include "pipe/p_context.h"
34 #include "state_tracker/st_context.h"
35 #include "state_tracker/st_public.h"
36 #include "shared/stw_device.h"
37 #include "shared/stw_winsys.h"
38 #include "shared/stw_framebuffer.h"
39 #include "shared/stw_pixelformat.h"
40 #include "stw_public.h"
41 #include "stw_context.h"
42
43 static HDC current_hdc = NULL;
44 static UINT_PTR current_hglrc = 0;
45
46 BOOL
47 stw_copy_context(
48 UINT_PTR hglrcSrc,
49 UINT_PTR hglrcDst,
50 UINT mask )
51 {
52 struct stw_context *src;
53 struct stw_context *dst;
54 BOOL ret = FALSE;
55
56 pipe_mutex_lock( stw_dev->mutex );
57
58 src = stw_lookup_context( hglrcSrc );
59 dst = stw_lookup_context( hglrcDst );
60
61 if (src && dst) {
62 /* FIXME */
63 (void) src;
64 (void) dst;
65 (void) mask;
66 }
67
68 pipe_mutex_unlock( stw_dev->mutex );
69
70 return ret;
71 }
72
73 UINT_PTR
74 stw_create_layer_context(
75 HDC hdc,
76 int iLayerPlane )
77 {
78 uint pfi;
79 const struct pixelformat_info *pf = NULL;
80 struct stw_context *ctx = NULL;
81 GLvisual *visual = NULL;
82 struct pipe_context *pipe = NULL;
83 UINT_PTR hglrc;
84
85 if(!stw_dev)
86 return 0;
87
88 if (iLayerPlane != 0)
89 return 0;
90
91 pfi = stw_pixelformat_get( hdc );
92 if (pfi == 0)
93 return 0;
94
95 pf = pixelformat_get_info( pfi - 1 );
96
97 ctx = CALLOC_STRUCT( stw_context );
98 if (ctx == NULL)
99 return 0;
100
101 ctx->hdc = hdc;
102 ctx->color_bits = GetDeviceCaps( ctx->hdc, BITSPIXEL );
103
104 /* Create visual based on flags
105 */
106 visual = _mesa_create_visual(
107 GL_TRUE,
108 (pf->flags & PF_FLAG_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
109 GL_FALSE,
110 pf->color.redbits,
111 pf->color.greenbits,
112 pf->color.bluebits,
113 pf->alpha.alphabits,
114 0,
115 pf->depth.depthbits,
116 pf->depth.stencilbits,
117 0,
118 0,
119 0,
120 0,
121 (pf->flags & PF_FLAG_MULTISAMPLED) ? stw_query_samples() : 0 );
122 if (visual == NULL)
123 goto fail;
124
125 pipe = stw_dev->stw_winsys->create_context( stw_dev->screen );
126 if (pipe == NULL)
127 goto fail;
128
129 assert(!pipe->priv);
130 pipe->priv = hdc;
131
132 ctx->st = st_create_context( pipe, visual, NULL );
133 if (ctx->st == NULL)
134 goto fail;
135
136 ctx->st->ctx->DriverCtx = ctx;
137
138 pipe_mutex_lock( stw_dev->mutex );
139 {
140 UINT_PTR i;
141
142 for (i = 0; i < STW_CONTEXT_MAX; i++) {
143 if (stw_dev->ctx_array[i].ctx == NULL)
144 break;
145 }
146
147 /* No slot available, fail:
148 */
149 if (i == STW_CONTEXT_MAX)
150 goto done;
151
152 stw_dev->ctx_array[i].ctx = ctx;
153
154 /* success:
155 */
156 hglrc = i + 1;
157 }
158 done:
159 pipe_mutex_unlock( stw_dev->mutex );
160
161 return hglrc;
162
163 fail:
164 if (visual)
165 _mesa_destroy_visual( visual );
166
167 if (pipe)
168 pipe->destroy( pipe );
169
170 FREE( ctx );
171 return 0;
172 }
173
174 BOOL
175 stw_delete_context(
176 UINT_PTR hglrc )
177 {
178 struct stw_context *ctx ;
179 BOOL ret = FALSE;
180
181 if (!stw_dev)
182 return FALSE;
183
184 pipe_mutex_lock( stw_dev->mutex );
185
186 ctx = stw_lookup_context(hglrc);
187 if (ctx) {
188 GLcontext *glctx = ctx->st->ctx;
189 GET_CURRENT_CONTEXT( glcurctx );
190 struct stw_framebuffer *fb;
191
192 /* Unbind current if deleting current context.
193 */
194 if (glcurctx == glctx)
195 st_make_current( NULL, NULL, NULL );
196
197 fb = framebuffer_from_hdc( ctx->hdc );
198 if (fb)
199 framebuffer_destroy( fb );
200
201 if (WindowFromDC( ctx->hdc ) != NULL)
202 ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
203
204 st_destroy_context( ctx->st );
205
206 FREE( ctx );
207
208 stw_dev->ctx_array[hglrc - 1].ctx = NULL;
209
210 ret = TRUE;
211 }
212
213 pipe_mutex_unlock( stw_dev->mutex );
214
215 return ret;
216 }
217
218 BOOL
219 stw_release_context(
220 UINT_PTR hglrc )
221 {
222 BOOL ret = FALSE;
223
224 if (!stw_dev)
225 return ret;
226
227 pipe_mutex_lock( stw_dev->mutex );
228 {
229 struct stw_context *ctx;
230
231 /* XXX: The expectation is that ctx is the same context which is
232 * current for this thread. We should check that and return False
233 * if not the case.
234 */
235 ctx = stw_lookup_context( hglrc );
236 if (ctx == NULL)
237 goto done;
238
239 if (stw_make_current( NULL, 0 ) == FALSE)
240 goto done;
241
242 ret = TRUE;
243 }
244 done:
245 pipe_mutex_unlock( stw_dev->mutex );
246
247 return ret;
248 }
249
250 /* Find the width and height of the window named by hdc.
251 */
252 static void
253 get_window_size( HDC hdc, GLuint *width, GLuint *height )
254 {
255 if (WindowFromDC( hdc )) {
256 RECT rect;
257
258 GetClientRect( WindowFromDC( hdc ), &rect );
259 *width = rect.right - rect.left;
260 *height = rect.bottom - rect.top;
261 }
262 else {
263 *width = GetDeviceCaps( hdc, HORZRES );
264 *height = GetDeviceCaps( hdc, VERTRES );
265 }
266 }
267
268 UINT_PTR
269 stw_get_current_context( void )
270 {
271 return current_hglrc;
272 }
273
274 HDC
275 stw_get_current_dc( void )
276 {
277 return current_hdc;
278 }
279
280 BOOL
281 stw_make_current(
282 HDC hdc,
283 UINT_PTR hglrc )
284 {
285 struct stw_context *ctx;
286 GET_CURRENT_CONTEXT( glcurctx );
287 struct stw_framebuffer *fb;
288 GLuint width = 0;
289 GLuint height = 0;
290
291 if (!stw_dev)
292 return FALSE;
293
294 pipe_mutex_lock( stw_dev->mutex );
295 ctx = stw_lookup_context( hglrc );
296 pipe_mutex_unlock( stw_dev->mutex );
297
298 if (ctx == NULL)
299 return FALSE;
300
301 current_hdc = hdc;
302 current_hglrc = hglrc;
303
304 if (hdc == NULL || hglrc == 0) {
305 st_make_current( NULL, NULL, NULL );
306 return TRUE;
307 }
308
309 /* Return if already current.
310 */
311 if (glcurctx != NULL) {
312 struct stw_context *curctx = (struct stw_context *) glcurctx->DriverCtx;
313
314 if (curctx != NULL && curctx == ctx && ctx->hdc == hdc)
315 return TRUE;
316 }
317
318 fb = framebuffer_from_hdc( hdc );
319
320 if (hdc != NULL)
321 get_window_size( hdc, &width, &height );
322
323 /* Lazy creation of framebuffers.
324 */
325 if (fb == NULL && ctx != NULL && hdc != NULL) {
326 GLvisual *visual = &ctx->st->ctx->Visual;
327
328 fb = framebuffer_create( hdc, visual, width, height );
329 if (fb == NULL)
330 return FALSE;
331
332 fb->dib_hDC = CreateCompatibleDC( hdc );
333 fb->hbmDIB = NULL;
334 fb->pbPixels = NULL;
335 }
336
337 if (ctx && fb) {
338 st_make_current( ctx->st, fb->stfb, fb->stfb );
339 framebuffer_resize( fb, width, height );
340 ctx->hdc = hdc;
341 ctx->st->pipe->priv = hdc;
342 }
343 else {
344 /* Detach */
345 st_make_current( NULL, NULL, NULL );
346 }
347
348 return TRUE;
349 }