f3c7af93f503aa99e97c33da1e99f04277b5828a
[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 ctx->pfi = pf;
157
158 pipe_mutex_lock( stw_dev->mutex );
159 hglrc = handle_table_add(stw_dev->ctx_table, ctx);
160 pipe_mutex_unlock( stw_dev->mutex );
161
162 /* Success?
163 */
164 if (hglrc != 0)
165 return hglrc;
166
167 fail:
168 if (visual)
169 _mesa_destroy_visual( visual );
170
171 if (pipe)
172 pipe->destroy( pipe );
173
174 FREE( ctx );
175 return 0;
176 }
177
178 BOOL
179 stw_delete_context(
180 UINT_PTR hglrc )
181 {
182 struct stw_context *ctx ;
183 BOOL ret = FALSE;
184
185 if (!stw_dev)
186 return FALSE;
187
188 pipe_mutex_lock( stw_dev->mutex );
189 ctx = stw_lookup_context_locked(hglrc);
190 handle_table_remove(stw_dev->ctx_table, hglrc);
191 pipe_mutex_unlock( stw_dev->mutex );
192
193 if (ctx) {
194 GLcontext *glctx = ctx->st->ctx;
195 GET_CURRENT_CONTEXT( glcurctx );
196 struct stw_framebuffer *fb;
197
198 /* Unbind current if deleting current context.
199 */
200 if (glcurctx == glctx)
201 st_make_current( NULL, NULL, NULL );
202
203 fb = stw_framebuffer_from_hdc( ctx->hdc );
204 if (fb)
205 stw_framebuffer_destroy( fb );
206
207 if (WindowFromDC( ctx->hdc ) != NULL)
208 ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc );
209
210 st_destroy_context(ctx->st);
211 FREE(ctx);
212
213 ret = TRUE;
214 }
215
216 return ret;
217 }
218
219 BOOL
220 stw_release_context(
221 UINT_PTR hglrc )
222 {
223 struct stw_context *ctx;
224
225 if (!stw_dev)
226 return FALSE;
227
228 pipe_mutex_lock( stw_dev->mutex );
229 ctx = stw_lookup_context_locked( hglrc );
230 pipe_mutex_unlock( stw_dev->mutex );
231
232 if (!ctx)
233 return FALSE;
234
235 /* The expectation is that ctx is the same context which is
236 * current for this thread. We should check that and return False
237 * if not the case.
238 */
239 {
240 GLcontext *glctx = ctx->st->ctx;
241 GET_CURRENT_CONTEXT( glcurctx );
242
243 if (glcurctx != glctx)
244 return FALSE;
245 }
246
247 if (stw_make_current( NULL, 0 ) == FALSE)
248 return FALSE;
249
250 return TRUE;
251 }
252
253 /* Find the width and height of the window named by hdc.
254 */
255 static void
256 stw_get_window_size( HDC hdc, GLuint *width, GLuint *height )
257 {
258 if (WindowFromDC( hdc )) {
259 RECT rect;
260
261 GetClientRect( WindowFromDC( hdc ), &rect );
262 *width = rect.right - rect.left;
263 *height = rect.bottom - rect.top;
264 }
265 else {
266 *width = GetDeviceCaps( hdc, HORZRES );
267 *height = GetDeviceCaps( hdc, VERTRES );
268 }
269 }
270
271 UINT_PTR
272 stw_get_current_context( void )
273 {
274 return stw_tls_get_data()->currentGLRC;
275 }
276
277 HDC
278 stw_get_current_dc( void )
279 {
280 return stw_tls_get_data()->currentDC;
281 }
282
283 BOOL
284 stw_make_current(
285 HDC hdc,
286 UINT_PTR hglrc )
287 {
288 struct stw_context *ctx;
289 GET_CURRENT_CONTEXT( glcurctx );
290 struct stw_framebuffer *fb;
291 GLuint width = 0;
292 GLuint height = 0;
293 struct stw_context *curctx;
294
295 if (!stw_dev)
296 return FALSE;
297
298 pipe_mutex_lock( stw_dev->mutex );
299 ctx = stw_lookup_context_locked( hglrc );
300 pipe_mutex_unlock( stw_dev->mutex );
301
302 stw_tls_get_data()->currentDC = hdc;
303 stw_tls_get_data()->currentGLRC = hglrc;
304
305 if (glcurctx != NULL) {
306 curctx = (struct stw_context *) glcurctx->DriverCtx;
307
308 if (curctx != ctx)
309 st_flush(glcurctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
310 }
311
312 if (hdc == NULL || hglrc == 0) {
313 st_make_current( NULL, NULL, NULL );
314 return TRUE;
315 }
316
317 /* Return if already current.
318 */
319 if (glcurctx != NULL) {
320 if (curctx != NULL && curctx == ctx && ctx->hdc == hdc)
321 return TRUE;
322 }
323
324 fb = stw_framebuffer_from_hdc( hdc );
325
326 if (hdc != NULL)
327 stw_get_window_size( hdc, &width, &height );
328
329 /* Lazy creation of stw_framebuffers.
330 */
331 if (fb == NULL && ctx != NULL && hdc != NULL) {
332 GLvisual *visual = &ctx->st->ctx->Visual;
333
334 fb = stw_framebuffer_create( hdc, visual, ctx->pfi, width, height );
335 if (fb == NULL)
336 return FALSE;
337 }
338
339 if (ctx && fb) {
340 pipe_mutex_lock( fb->mutex );
341 st_make_current( ctx->st, fb->stfb, fb->stfb );
342 st_resize_framebuffer( fb->stfb, width, height );
343 pipe_mutex_unlock( fb->mutex );
344
345 ctx->hdc = hdc;
346 ctx->st->pipe->priv = hdc;
347 }
348 else {
349 /* Detach */
350 st_make_current( NULL, NULL, NULL );
351 }
352
353 return TRUE;
354 }