1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #include "main/context.h"
31 #include "pipe/p_format.h"
32 #include "pipe/p_screen.h"
33 #include "state_tracker/st_context.h"
34 #include "state_tracker/st_public.h"
37 #include "trace/tr_screen.h"
38 #include "trace/tr_texture.h"
41 #include "stw_framebuffer.h"
42 #include "stw_device.h"
43 #include "stw_public.h"
44 #include "stw_winsys.h"
49 * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
50 * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
52 static LRESULT CALLBACK
58 struct stw_tls_data
*tls_data
;
59 PCWPSTRUCT pParams
= (PCWPSTRUCT
)lParam
;
61 tls_data
= stw_tls_get_data();
66 return CallNextHookEx(tls_data
->hCallWndProcHook
, nCode
, wParam
, lParam
);
68 if (pParams
->message
== WM_SIZE
&& pParams
->wParam
!= SIZE_MINIMIZED
) {
69 struct stw_framebuffer
*fb
;
71 pipe_mutex_lock( stw_dev
->mutex
);
72 for (fb
= stw_dev
->fb_head
; fb
!= NULL
; fb
= fb
->next
)
73 if (fb
->hWnd
== pParams
->hwnd
)
75 pipe_mutex_unlock( stw_dev
->mutex
);
78 unsigned width
= LOWORD( pParams
->lParam
);
79 unsigned height
= HIWORD( pParams
->lParam
);
81 /* FIXME: The mesa statetracker makes the assumptions that only
82 * one context is using the framebuffer, and that that context is the
83 * current one. However neither holds true, as WGL allows more than
84 * one context to be bound to the same drawable, and this function can
85 * be called from any thread.
87 pipe_mutex_lock( fb
->mutex
);
88 st_resize_framebuffer( fb
->stfb
, width
, height
);
89 pipe_mutex_unlock( fb
->mutex
);
93 return CallNextHookEx(tls_data
->hCallWndProcHook
, nCode
, wParam
, lParam
);
98 * Create a new framebuffer object which will correspond to the given HDC.
100 struct stw_framebuffer
*
101 stw_framebuffer_create_locked(
105 struct stw_framebuffer
*fb
;
106 const struct stw_pixelformat_info
*pfi
;
108 fb
= CALLOC_STRUCT( stw_framebuffer
);
113 fb
->hWnd
= WindowFromDC( hdc
);
114 fb
->iPixelFormat
= iPixelFormat
;
116 fb
->pfi
= pfi
= stw_pixelformat_get_info( iPixelFormat
- 1 );
118 stw_pixelformat_visual(&fb
->visual
, pfi
);
120 pipe_mutex_init( fb
->mutex
);
122 fb
->next
= stw_dev
->fb_head
;
123 stw_dev
->fb_head
= fb
;
130 stw_framebuffer_get_size( struct stw_framebuffer
*fb
, GLuint
*pwidth
, GLuint
*pheight
)
132 GLuint width
, height
;
136 GetClientRect( fb
->hWnd
, &rect
);
137 width
= rect
.right
- rect
.left
;
138 height
= rect
.bottom
- rect
.top
;
141 width
= GetDeviceCaps( fb
->hDC
, HORZRES
);
142 height
= GetDeviceCaps( fb
->hDC
, VERTRES
);
156 stw_framebuffer_allocate(
157 struct stw_framebuffer
*fb
)
159 pipe_mutex_lock( fb
->mutex
);
162 const struct stw_pixelformat_info
*pfi
= fb
->pfi
;
163 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
164 GLuint width
, height
;
166 colorFormat
= pfi
->color_format
;
168 assert(pf_layout( pfi
->depth_stencil_format
) == PIPE_FORMAT_LAYOUT_RGBAZS
);
170 if(pf_get_component_bits( pfi
->depth_stencil_format
, PIPE_FORMAT_COMP_Z
))
171 depthFormat
= pfi
->depth_stencil_format
;
173 depthFormat
= PIPE_FORMAT_NONE
;
175 if(pf_get_component_bits( pfi
->depth_stencil_format
, PIPE_FORMAT_COMP_S
))
176 stencilFormat
= pfi
->depth_stencil_format
;
178 stencilFormat
= PIPE_FORMAT_NONE
;
180 stw_framebuffer_get_size(fb
, &width
, &height
);
182 fb
->stfb
= st_create_framebuffer(
192 pipe_mutex_unlock( fb
->mutex
);
194 return fb
->stfb
? TRUE
: FALSE
;
199 stw_framebuffer_resize(
200 struct stw_framebuffer
*fb
)
202 GLuint width
, height
;
204 stw_framebuffer_get_size(fb
, &width
, &height
);
205 st_resize_framebuffer(fb
->stfb
, width
, height
);
210 stw_framebuffer_destroy(
211 struct stw_framebuffer
*fb
)
213 struct stw_framebuffer
**link
;
215 pipe_mutex_lock( stw_dev
->mutex
);
217 link
= &stw_dev
->fb_head
;
218 while (link
&& *link
!= fb
)
219 link
= &(*link
)->next
;
225 pipe_mutex_unlock( stw_dev
->mutex
);
227 st_unreference_framebuffer(fb
->stfb
);
229 pipe_mutex_destroy( fb
->mutex
);
236 stw_framebuffer_cleanup( void )
238 struct stw_framebuffer
*fb
;
239 struct stw_framebuffer
*next
;
241 pipe_mutex_lock( stw_dev
->mutex
);
243 fb
= stw_dev
->fb_head
;
246 stw_framebuffer_destroy(fb
);
249 stw_dev
->fb_head
= NULL
;
251 pipe_mutex_unlock( stw_dev
->mutex
);
256 * Given an hdc, return the corresponding stw_framebuffer.
258 struct stw_framebuffer
*
259 stw_framebuffer_from_hdc_locked(
262 struct stw_framebuffer
*fb
;
264 for (fb
= stw_dev
->fb_head
; fb
!= NULL
; fb
= fb
->next
)
273 * Given an hdc, return the corresponding stw_framebuffer.
275 struct stw_framebuffer
*
276 stw_framebuffer_from_hdc(
279 struct stw_framebuffer
*fb
;
281 pipe_mutex_lock( stw_dev
->mutex
);
282 fb
= stw_framebuffer_from_hdc_locked(hdc
);
283 pipe_mutex_unlock( stw_dev
->mutex
);
296 struct stw_framebuffer
*fb
;
298 index
= (uint
) iPixelFormat
- 1;
299 count
= stw_pixelformat_get_extended_count();
303 pipe_mutex_lock( stw_dev
->mutex
);
305 fb
= stw_framebuffer_from_hdc_locked(hdc
);
307 /* SetPixelFormat must be called only once */
308 pipe_mutex_unlock( stw_dev
->mutex
);
312 fb
= stw_framebuffer_create_locked(hdc
, iPixelFormat
);
314 pipe_mutex_unlock( stw_dev
->mutex
);
318 pipe_mutex_unlock( stw_dev
->mutex
);
320 /* Some applications mistakenly use the undocumented wglSetPixelFormat
321 * function instead of SetPixelFormat, so we call SetPixelFormat here to
322 * avoid opengl32.dll's wglCreateContext to fail */
323 if (GetPixelFormat(hdc
) == 0) {
324 SetPixelFormat(hdc
, iPixelFormat
, NULL
);
335 struct stw_framebuffer
*fb
;
337 fb
= stw_framebuffer_from_hdc(hdc
);
341 return fb
->iPixelFormat
;
349 struct stw_framebuffer
*fb
;
350 struct pipe_screen
*screen
;
351 struct pipe_surface
*surface
;
353 fb
= stw_framebuffer_from_hdc( hdc
);
357 pipe_mutex_lock( fb
->mutex
);
359 /* If we're swapping the buffer associated with the current context
360 * we have to flush any pending rendering commands first.
362 st_notify_swapbuffers( fb
->stfb
);
364 screen
= stw_dev
->screen
;
366 if(!st_get_framebuffer_surface( fb
->stfb
, ST_SURFACE_BACK_LEFT
, &surface
)) {
367 /* FIXME: this shouldn't happen, but does on glean */
368 pipe_mutex_unlock( fb
->mutex
);
373 if(stw_dev
->trace_running
) {
374 screen
= trace_screen(screen
)->screen
;
375 surface
= trace_surface(surface
)->surface
;
379 stw_dev
->stw_winsys
->flush_frontbuffer( screen
, surface
, hdc
);
381 pipe_mutex_unlock( fb
->mutex
);
388 stw_swap_layer_buffers(
392 if(fuPlanes
& WGL_SWAP_MAIN_PLANE
)
393 return stw_swap_buffers(hdc
);
400 stw_framebuffer_init_thread(void)
402 struct stw_tls_data
*tls_data
;
404 tls_data
= stw_tls_get_data();
408 tls_data
->hCallWndProcHook
= SetWindowsHookEx(WH_CALLWNDPROC
,
409 stw_call_window_proc
,
411 GetCurrentThreadId());
412 if(tls_data
->hCallWndProcHook
== NULL
)
419 stw_framebuffer_cleanup_thread(void)
421 struct stw_tls_data
*tls_data
;
423 tls_data
= stw_tls_get_data();
427 if(tls_data
->hCallWndProcHook
) {
428 UnhookWindowsHookEx(tls_data
->hCallWndProcHook
);
429 tls_data
->hCallWndProcHook
= NULL
;