wgl: Keep copies of the PIXELFORMATDESCRIPTOR structures.
[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
37 #ifdef DEBUG
38 #include "trace/tr_screen.h"
39 #include "trace/tr_context.h"
40 #endif
41
42 #include "shared/stw_device.h"
43 #include "shared/stw_winsys.h"
44 #include "shared/stw_framebuffer.h"
45 #include "shared/stw_pixelformat.h"
46 #include "stw_public.h"
47 #include "stw_context.h"
48 #include "stw_tls.h"
49
50 BOOL
51 stw_copy_context(
52 UINT_PTR hglrcSrc,
53 UINT_PTR hglrcDst,
54 UINT mask )
55 {
56 struct stw_context *src;
57 struct stw_context *dst;
58 BOOL ret = FALSE;
59
60 pipe_mutex_lock( stw_dev->mutex );
61
62 src = stw_lookup_context_locked( hglrcSrc );
63 dst = stw_lookup_context_locked( hglrcDst );
64
65 if (src && dst) {
66 /* FIXME */
67 (void) src;
68 (void) dst;
69 (void) mask;
70 }
71
72 pipe_mutex_unlock( stw_dev->mutex );
73
74 return ret;
75 }
76
77 UINT_PTR
78 stw_create_layer_context(
79 HDC hdc,
80 int iLayerPlane )
81 {
82 uint pfi;
83 const struct stw_pixelformat_info *pf = NULL;
84 struct stw_context *ctx = NULL;
85 GLvisual *visual = NULL;
86 struct pipe_screen *screen = NULL;
87 struct pipe_context *pipe = NULL;
88 UINT_PTR hglrc = 0;
89
90 if(!stw_dev)
91 return 0;
92
93 if (iLayerPlane != 0)
94 return 0;
95
96 pfi = stw_pixelformat_get( hdc );
97 if (pfi == 0)
98 return 0;
99
100 pf = stw_pixelformat_get_info( pfi - 1 );
101
102 ctx = CALLOC_STRUCT( stw_context );
103 if (ctx == NULL)
104 return 0;
105
106 ctx->hdc = hdc;
107 ctx->color_bits = GetDeviceCaps( ctx->hdc, BITSPIXEL );
108
109 /* Create visual based on flags
110 */
111 visual = _mesa_create_visual(
112 (pf->pfd.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE,
113 (pf->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
114 (pf->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
115 pf->pfd.cRedBits,
116 pf->pfd.cGreenBits,
117 pf->pfd.cBlueBits,
118 pf->pfd.cAlphaBits,
119 (pf->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pf->pfd.cColorBits : 0,
120 pf->pfd.cDepthBits,
121 pf->pfd.cStencilBits,
122 pf->pfd.cAccumRedBits,
123 pf->pfd.cAccumGreenBits,
124 pf->pfd.cAccumBlueBits,
125 pf->pfd.cAccumAlphaBits,
126 pf->numSamples );
127 if (visual == NULL)
128 goto fail;
129
130 screen = stw_dev->screen;
131
132 #ifdef DEBUG
133 /* Unwrap screen */
134 if(stw_dev->trace_running)
135 screen = trace_screen(screen)->screen;
136 #endif
137
138 pipe = stw_dev->stw_winsys->create_context( screen );
139 if (pipe == NULL)
140 goto fail;
141
142 #ifdef DEBUG
143 /* Wrap context */
144 if(stw_dev->trace_running)
145 pipe = trace_context_create(stw_dev->screen, pipe);
146 #endif
147
148 assert(!pipe->priv);
149 pipe->priv = hdc;
150
151 ctx->st = st_create_context( pipe, visual, NULL );
152 if (ctx->st == NULL)
153 goto fail;
154
155 ctx->st->ctx->DriverCtx = ctx;
156
157 pipe_mutex_lock( stw_dev->mutex );
158 hglrc = handle_table_add(stw_dev->ctx_table, ctx);
159 pipe_mutex_unlock( stw_dev->mutex );
160
161 /* Success?
162 */
163 if (hglrc != 0)
164 return hglrc;
165
166 fail:
167 if (visual)
168 _mesa_destroy_visual( visual );
169
170 if (pipe)
171 pipe->destroy( pipe );
172
173 FREE( ctx );
174 return 0;
175 }
176
177 BOOL
178 stw_delete_context(
179 UINT_PTR hglrc )
180 {
181 struct stw_context *ctx ;
182 BOOL ret = FALSE;
183
184 if (!stw_dev)
185 return FALSE;
186
187 pipe_mutex_lock( stw_dev->mutex );
188 ctx = stw_lookup_context_locked(hglrc);
189 handle_table_remove(stw_dev->ctx_table, hglrc);
190 pipe_mutex_unlock( stw_dev->mutex );
191
192 if (ctx) {
193 GLcontext *glctx = ctx->st->ctx;
194 GET_CURRENT_CONTEXT( glcurctx );
195 struct stw_framebuffer *fb;
196
197 /* Unbind current if deleting current context.
198 */
199 if (glcurctx == glctx)
200 st_make_current( NULL, NULL, NULL );
201
202 fb = stw_framebuffer_from_hdc( ctx->hdc );
203 if (fb)
204 stw_framebuffer_destroy( fb );
205
206 if (WindowFromDC( ctx->hdc ) != NULL)
207 ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
208
209 st_destroy_context(ctx->st);
210 FREE(ctx);
211
212 ret = TRUE;
213 }
214
215 return ret;
216 }
217
218 BOOL
219 stw_release_context(
220 UINT_PTR hglrc )
221 {
222 struct stw_context *ctx;
223
224 if (!stw_dev)
225 return FALSE;
226
227 pipe_mutex_lock( stw_dev->mutex );
228 ctx = stw_lookup_context_locked( hglrc );
229 pipe_mutex_unlock( stw_dev->mutex );
230
231 if (!ctx)
232 return FALSE;
233
234 /* The expectation is that ctx is the same context which is
235 * current for this thread. We should check that and return False
236 * if not the case.
237 */
238 {
239 GLcontext *glctx = ctx->st->ctx;
240 GET_CURRENT_CONTEXT( glcurctx );
241
242 if (glcurctx != glctx)
243 return FALSE;
244 }
245
246 if (stw_make_current( NULL, 0 ) == FALSE)
247 return FALSE;
248
249 return TRUE;
250 }
251
252 /* Find the width and height of the window named by hdc.
253 */
254 static void
255 stw_get_window_size( HDC hdc, GLuint *width, GLuint *height )
256 {
257 if (WindowFromDC( hdc )) {
258 RECT rect;
259
260 GetClientRect( WindowFromDC( hdc ), &rect );
261 *width = rect.right - rect.left;
262 *height = rect.bottom - rect.top;
263 }
264 else {
265 *width = GetDeviceCaps( hdc, HORZRES );
266 *height = GetDeviceCaps( hdc, VERTRES );
267 }
268 }
269
270 UINT_PTR
271 stw_get_current_context( void )
272 {
273 return stw_tls_get_data()->currentGLRC;
274 }
275
276 HDC
277 stw_get_current_dc( void )
278 {
279 return stw_tls_get_data()->currentDC;
280 }
281
282 BOOL
283 stw_make_current(
284 HDC hdc,
285 UINT_PTR hglrc )
286 {
287 struct stw_context *ctx;
288 GET_CURRENT_CONTEXT( glcurctx );
289 struct stw_framebuffer *fb;
290 GLuint width = 0;
291 GLuint height = 0;
292 struct stw_context *curctx;
293
294 if (!stw_dev)
295 return FALSE;
296
297 pipe_mutex_lock( stw_dev->mutex );
298 ctx = stw_lookup_context_locked( hglrc );
299 pipe_mutex_unlock( stw_dev->mutex );
300
301 stw_tls_get_data()->currentDC = hdc;
302 stw_tls_get_data()->currentGLRC = hglrc;
303
304 if (glcurctx != NULL) {
305 curctx = (struct stw_context *) glcurctx->DriverCtx;
306
307 if (curctx != ctx)
308 st_flush(glcurctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
309 }
310
311 if (hdc == NULL || hglrc == 0) {
312 st_make_current( NULL, NULL, NULL );
313 return TRUE;
314 }
315
316 /* Return if already current.
317 */
318 if (glcurctx != NULL) {
319 if (curctx != NULL && curctx == ctx && ctx->hdc == hdc)
320 return TRUE;
321 }
322
323 fb = stw_framebuffer_from_hdc( hdc );
324
325 if (hdc != NULL)
326 stw_get_window_size( hdc, &width, &height );
327
328 /* Lazy creation of stw_framebuffers.
329 */
330 if (fb == NULL && ctx != NULL && hdc != NULL) {
331 GLvisual *visual = &ctx->st->ctx->Visual;
332
333 fb = stw_framebuffer_create( hdc, visual, width, height );
334 if (fb == NULL)
335 return FALSE;
336 }
337
338 if (ctx && fb) {
339 st_make_current( ctx->st, fb->stfb, fb->stfb );
340 stw_framebuffer_resize( fb, width, height );
341 ctx->hdc = hdc;
342 ctx->st->pipe->priv = hdc;
343 }
344 else {
345 /* Detach */
346 st_make_current( NULL, NULL, NULL );
347 }
348
349 return TRUE;
350 }