wgl: Remove unused member.
[mesa.git] / src / gallium / state_trackers / wgl / shared / stw_framebuffer.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/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"
35
36 #ifdef DEBUG
37 #include "trace/tr_screen.h"
38 #include "trace/tr_texture.h"
39 #endif
40
41 #include "stw_framebuffer.h"
42 #include "stw_device.h"
43 #include "stw_public.h"
44 #include "stw_winsys.h"
45 #include "stw_tls.h"
46
47
48 void
49 stw_framebuffer_resize(
50 struct stw_framebuffer *fb,
51 GLuint width,
52 GLuint height )
53 {
54 st_resize_framebuffer( fb->stfb, width, height );
55 }
56
57 /**
58 * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
59 * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
60 */
61 static LRESULT CALLBACK
62 stw_call_window_proc(
63 int nCode,
64 WPARAM wParam,
65 LPARAM lParam )
66 {
67 struct stw_tls_data *tls_data;
68 PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
69
70 tls_data = stw_tls_get_data();
71 if(!tls_data)
72 return 0;
73
74 if (nCode < 0)
75 return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
76
77 if (pParams->message == WM_SIZE && pParams->wParam != SIZE_MINIMIZED) {
78 struct stw_framebuffer *fb;
79
80 pipe_mutex_lock( stw_dev->mutex );
81 for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
82 if (fb->hWnd == pParams->hwnd)
83 break;
84 pipe_mutex_unlock( stw_dev->mutex );
85
86 if(fb) {
87 unsigned width = LOWORD( pParams->lParam );
88 unsigned height = HIWORD( pParams->lParam );
89 stw_framebuffer_resize( fb, width, height );
90 }
91 }
92
93 return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
94 }
95
96 static INLINE boolean
97 stw_is_supported_color(enum pipe_format format)
98 {
99 struct pipe_screen *screen = stw_dev->screen;
100 return screen->is_format_supported(screen, format, PIPE_TEXTURE_2D,
101 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0);
102 }
103
104 static INLINE boolean
105 stw_is_supported_depth_stencil(enum pipe_format format)
106 {
107 struct pipe_screen *screen = stw_dev->screen;
108 return screen->is_format_supported(screen, format, PIPE_TEXTURE_2D,
109 PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
110 }
111
112 /* Create a new framebuffer object which will correspond to the given HDC.
113 */
114 struct stw_framebuffer *
115 stw_framebuffer_create(
116 HDC hdc,
117 GLvisual *visual,
118 GLuint width,
119 GLuint height )
120 {
121 struct stw_framebuffer *fb;
122 enum pipe_format colorFormat, depthFormat, stencilFormat;
123
124 /* Determine PIPE_FORMATs for buffers.
125 */
126
127 if(visual->alphaBits <= 0 && visual->redBits <= 5 && visual->blueBits <= 6 && visual->greenBits <= 5 &&
128 stw_is_supported_color(PIPE_FORMAT_R5G6B5_UNORM)) {
129 colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
130 }
131 else if(visual->alphaBits <= 0 && visual->redBits <= 8 && visual->blueBits <= 8 && visual->greenBits <= 8 &&
132 stw_is_supported_color(PIPE_FORMAT_X8R8G8B8_UNORM)) {
133 colorFormat = PIPE_FORMAT_X8R8G8B8_UNORM;
134 }
135 else if(visual->alphaBits <= 1 && visual->redBits <= 5 && visual->blueBits <= 5 && visual->greenBits <= 5 &&
136 stw_is_supported_color(PIPE_FORMAT_A1R5G5B5_UNORM)) {
137 colorFormat = PIPE_FORMAT_A1R5G5B5_UNORM;
138 }
139 else if(visual->alphaBits <= 4 && visual->redBits <= 4 && visual->blueBits <= 4 && visual->greenBits <= 4 &&
140 stw_is_supported_color(PIPE_FORMAT_A4R4G4B4_UNORM)) {
141 colorFormat = PIPE_FORMAT_A4R4G4B4_UNORM;
142 }
143 else if(visual->alphaBits <= 8 && visual->redBits <= 8 && visual->blueBits <= 8 && visual->greenBits <= 8 &&
144 stw_is_supported_color(PIPE_FORMAT_A8R8G8B8_UNORM)) {
145 colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
146 }
147 else {
148 assert(0);
149 return NULL;
150 }
151
152 if (visual->depthBits == 0)
153 depthFormat = PIPE_FORMAT_NONE;
154 else if (visual->depthBits <= 16 &&
155 stw_is_supported_depth_stencil(PIPE_FORMAT_Z16_UNORM))
156 depthFormat = PIPE_FORMAT_Z16_UNORM;
157 else if (visual->depthBits <= 24 && visual->stencilBits != 8 &&
158 stw_is_supported_depth_stencil(PIPE_FORMAT_X8Z24_UNORM)) {
159 depthFormat = PIPE_FORMAT_X8Z24_UNORM;
160 }
161 else if (visual->depthBits <= 24 && visual->stencilBits != 8 &&
162 stw_is_supported_depth_stencil(PIPE_FORMAT_Z24X8_UNORM)) {
163 depthFormat = PIPE_FORMAT_Z24X8_UNORM;
164 }
165 else if (visual->depthBits <= 24 && visual->stencilBits == 8 &&
166 stw_is_supported_depth_stencil(PIPE_FORMAT_S8Z24_UNORM)) {
167 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
168 }
169 else if (visual->depthBits <= 24 && visual->stencilBits == 8 &&
170 stw_is_supported_depth_stencil(PIPE_FORMAT_Z24S8_UNORM)) {
171 depthFormat = PIPE_FORMAT_Z24S8_UNORM;
172 }
173 else if(stw_is_supported_depth_stencil(PIPE_FORMAT_Z32_UNORM)) {
174 depthFormat = PIPE_FORMAT_Z32_UNORM;
175 }
176 else if(stw_is_supported_depth_stencil(PIPE_FORMAT_Z32_FLOAT)) {
177 depthFormat = PIPE_FORMAT_Z32_FLOAT;
178 }
179 else {
180 assert(0);
181 depthFormat = PIPE_FORMAT_NONE;
182 }
183
184 if (depthFormat == PIPE_FORMAT_S8Z24_UNORM ||
185 depthFormat == PIPE_FORMAT_Z24S8_UNORM) {
186 stencilFormat = depthFormat;
187 }
188 else if (visual->stencilBits == 8 &&
189 stw_is_supported_depth_stencil(PIPE_FORMAT_S8_UNORM)) {
190 stencilFormat = PIPE_FORMAT_S8_UNORM;
191 }
192 else {
193 stencilFormat = PIPE_FORMAT_NONE;
194 }
195
196 fb = CALLOC_STRUCT( stw_framebuffer );
197 if (fb == NULL)
198 return NULL;
199
200 fb->stfb = st_create_framebuffer(
201 visual,
202 colorFormat,
203 depthFormat,
204 stencilFormat,
205 width,
206 height,
207 (void *) fb );
208
209 fb->hDC = hdc;
210 fb->hWnd = WindowFromDC( hdc );
211
212 pipe_mutex_lock( stw_dev->mutex );
213 fb->next = stw_dev->fb_head;
214 stw_dev->fb_head = fb;
215 pipe_mutex_unlock( stw_dev->mutex );
216
217 return fb;
218 }
219
220 void
221 stw_framebuffer_destroy(
222 struct stw_framebuffer *fb )
223 {
224 struct stw_framebuffer **link;
225
226 pipe_mutex_lock( stw_dev->mutex );
227
228 link = &stw_dev->fb_head;
229 while (link && *link != fb)
230 link = &(*link)->next;
231 assert(*link);
232 if (link)
233 *link = fb->next;
234 fb->next = NULL;
235
236 pipe_mutex_unlock( stw_dev->mutex );
237
238 FREE( fb );
239 }
240
241 /**
242 * Given an hdc, return the corresponding stw_framebuffer.
243 */
244 struct stw_framebuffer *
245 stw_framebuffer_from_hdc(
246 HDC hdc )
247 {
248 struct stw_framebuffer *fb;
249
250 pipe_mutex_lock( stw_dev->mutex );
251 for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
252 if (fb->hDC == hdc)
253 break;
254 pipe_mutex_unlock( stw_dev->mutex );
255
256 return fb;
257 }
258
259
260 BOOL
261 stw_swap_buffers(
262 HDC hdc )
263 {
264 struct stw_framebuffer *fb;
265 struct pipe_screen *screen;
266 struct pipe_surface *surface;
267
268 fb = stw_framebuffer_from_hdc( hdc );
269 if (fb == NULL)
270 return FALSE;
271
272 /* If we're swapping the buffer associated with the current context
273 * we have to flush any pending rendering commands first.
274 */
275 st_notify_swapbuffers( fb->stfb );
276
277 screen = stw_dev->screen;
278
279 if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface ))
280 /* FIXME: this shouldn't happen, but does on glean */
281 return FALSE;
282
283 #ifdef DEBUG
284 if(stw_dev->trace_running) {
285 screen = trace_screen(screen)->screen;
286 surface = trace_surface(surface)->surface;
287 }
288 #endif
289
290 stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
291
292 return TRUE;
293 }
294
295
296 boolean
297 stw_framebuffer_init_thread(void)
298 {
299 struct stw_tls_data *tls_data;
300
301 tls_data = stw_tls_get_data();
302 if(!tls_data)
303 return FALSE;
304
305 tls_data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC,
306 stw_call_window_proc,
307 NULL,
308 GetCurrentThreadId());
309 if(tls_data->hCallWndProcHook == NULL)
310 return FALSE;
311
312 return TRUE;
313 }
314
315 void
316 stw_framebuffer_cleanup_thread(void)
317 {
318 struct stw_tls_data *tls_data;
319
320 tls_data = stw_tls_get_data();
321 if(!tls_data)
322 return;
323
324 if(tls_data->hCallWndProcHook) {
325 UnhookWindowsHookEx(tls_data->hCallWndProcHook);
326 tls_data->hCallWndProcHook = NULL;
327 }
328 }