2 * Mesa 3-D graphics library
5 * Copyright (C) 2010 LunarG Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 * Chia-I Wu <olv@lunarg.com>
31 #include "pipe/p_compiler.h"
32 #include "util/u_memory.h"
33 #include "util/u_format.h"
34 #include "util/u_inlines.h"
35 #include "gdi/gdi_sw_winsys.h"
37 #include "common/native_helper.h"
38 #include "common/native.h"
41 struct native_display base
;
44 struct native_event_handler
*event_handler
;
46 struct native_config
*configs
;
51 struct native_surface base
;
54 enum pipe_format color_format
;
56 struct gdi_display
*gdpy
;
58 unsigned int server_stamp
;
59 unsigned int client_stamp
;
61 struct resource_surface
*rsurf
;
64 static INLINE
struct gdi_display
*
65 gdi_display(const struct native_display
*ndpy
)
67 return (struct gdi_display
*) ndpy
;
70 static INLINE
struct gdi_surface
*
71 gdi_surface(const struct native_surface
*nsurf
)
73 return (struct gdi_surface
*) nsurf
;
77 * Update the geometry of the surface. This is a slow functions.
80 gdi_surface_update_geometry(struct native_surface
*nsurf
)
82 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
86 GetClientRect(gsurf
->hWnd
, &rect
);
87 w
= rect
.right
- rect
.left
;
88 h
= rect
.bottom
- rect
.top
;
90 if (resource_surface_set_size(gsurf
->rsurf
, w
, h
))
91 gsurf
->server_stamp
++;
95 * Update the buffers of the surface.
98 gdi_surface_update_buffers(struct native_surface
*nsurf
, uint buffer_mask
)
100 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
102 if (gsurf
->client_stamp
!= gsurf
->server_stamp
) {
103 gdi_surface_update_geometry(&gsurf
->base
);
104 gsurf
->client_stamp
= gsurf
->server_stamp
;
107 return resource_surface_add_resources(gsurf
->rsurf
, buffer_mask
);
111 * Emulate an invalidate event.
114 gdi_surface_invalidate(struct native_surface
*nsurf
)
116 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
117 struct gdi_display
*gdpy
= gsurf
->gdpy
;
119 gsurf
->server_stamp
++;
120 gdpy
->event_handler
->invalid_surface(&gdpy
->base
,
121 &gsurf
->base
, gsurf
->server_stamp
);
125 gdi_surface_flush_frontbuffer(struct native_surface
*nsurf
)
127 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
131 hDC
= GetDC(gsurf
->hWnd
);
132 ret
= resource_surface_present(gsurf
->rsurf
,
133 NATIVE_ATTACHMENT_FRONT_LEFT
, (void *) hDC
);
134 ReleaseDC(gsurf
->hWnd
, hDC
);
136 /* force buffers to be updated in next validation call */
137 gdi_surface_invalidate(&gsurf
->base
);
143 gdi_surface_swap_buffers(struct native_surface
*nsurf
)
145 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
149 hDC
= GetDC(gsurf
->hWnd
);
150 ret
= resource_surface_present(gsurf
->rsurf
,
151 NATIVE_ATTACHMENT_BACK_LEFT
, (void *) hDC
);
152 ReleaseDC(gsurf
->hWnd
, hDC
);
154 resource_surface_swap_buffers(gsurf
->rsurf
,
155 NATIVE_ATTACHMENT_FRONT_LEFT
, NATIVE_ATTACHMENT_BACK_LEFT
, TRUE
);
156 /* the front/back buffers have been swapped */
157 gdi_surface_invalidate(&gsurf
->base
);
163 gdi_surface_present(struct native_surface
*nsurf
,
164 enum native_attachment natt
,
170 if (preserve
|| swap_interval
)
174 case NATIVE_ATTACHMENT_FRONT_LEFT
:
175 ret
= gdi_surface_flush_frontbuffer(nsurf
);
177 case NATIVE_ATTACHMENT_BACK_LEFT
:
178 ret
= gdi_surface_swap_buffers(nsurf
);
189 gdi_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
190 unsigned int *seq_num
, struct pipe_resource
**textures
,
191 int *width
, int *height
)
193 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
196 if (!gdi_surface_update_buffers(&gsurf
->base
, attachment_mask
))
200 *seq_num
= gsurf
->client_stamp
;
203 resource_surface_get_resources(gsurf
->rsurf
, textures
, attachment_mask
);
205 resource_surface_get_size(gsurf
->rsurf
, &w
, &h
);
215 gdi_surface_wait(struct native_surface
*nsurf
)
221 gdi_surface_destroy(struct native_surface
*nsurf
)
223 struct gdi_surface
*gsurf
= gdi_surface(nsurf
);
225 resource_surface_destroy(gsurf
->rsurf
);
229 static struct native_surface
*
230 gdi_display_create_window_surface(struct native_display
*ndpy
,
231 EGLNativeWindowType win
,
232 const struct native_config
*nconf
)
234 struct gdi_display
*gdpy
= gdi_display(ndpy
);
235 struct gdi_surface
*gsurf
;
237 gsurf
= CALLOC_STRUCT(gdi_surface
);
242 gsurf
->color_format
= nconf
->color_format
;
243 gsurf
->hWnd
= (HWND
) win
;
245 gsurf
->rsurf
= resource_surface_create(gdpy
->base
.screen
,
247 PIPE_BIND_RENDER_TARGET
|
248 PIPE_BIND_SAMPLER_VIEW
|
249 PIPE_BIND_DISPLAY_TARGET
|
256 /* initialize the geometry */
257 gdi_surface_update_geometry(&gsurf
->base
);
259 gsurf
->base
.destroy
= gdi_surface_destroy
;
260 xsurf
->base
.present
= gdi_surface_present
;
261 gsurf
->base
.validate
= gdi_surface_validate
;
262 gsurf
->base
.wait
= gdi_surface_wait
;
268 fill_color_formats(struct native_display
*ndpy
, enum pipe_format formats
[8])
270 struct pipe_screen
*screen
= ndpy
->screen
;
273 enum pipe_format candidates
[] = {
275 PIPE_FORMAT_B8G8R8A8_UNORM
,
276 PIPE_FORMAT_A8R8G8B8_UNORM
,
278 PIPE_FORMAT_B8G8R8X8_UNORM
,
279 PIPE_FORMAT_X8R8G8B8_UNORM
,
281 PIPE_FORMAT_B5G6R5_UNORM
284 assert(Elements(candidates
) <= 8);
286 for (i
= 0; i
< Elements(candidates
); i
++) {
287 if (screen
->is_format_supported(screen
, candidates
[i
],
288 PIPE_TEXTURE_2D
, 0, PIPE_BIND_RENDER_TARGET
, 0))
289 formats
[count
++] = candidates
[i
];
295 static const struct native_config
**
296 gdi_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
298 struct gdi_display
*gdpy
= gdi_display(ndpy
);
299 const struct native_config
**configs
;
303 if (!gdpy
->configs
) {
304 enum pipe_format formats
[8];
307 count
= fill_color_formats(&gdpy
->base
, formats
);
309 gdpy
->configs
= CALLOC(count
, sizeof(*gdpy
->configs
));
313 for (i
= 0; i
< count
; i
++) {
314 struct native_config
*nconf
= &gdpy
->configs
[i
];
317 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
318 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
319 nconf
->color_format
= formats
[i
];
321 nconf
->window_bit
= TRUE
;
322 nconf
->slow_config
= TRUE
;
325 gdpy
->num_configs
= count
;
328 configs
= MALLOC(gdpy
->num_configs
* sizeof(*configs
));
330 for (i
= 0; i
< gdpy
->num_configs
; i
++)
331 configs
[i
] = (const struct native_config
*) &gdpy
->configs
[i
];
333 *num_configs
= gdpy
->num_configs
;
339 gdi_display_get_param(struct native_display
*ndpy
,
340 enum native_param_type param
)
345 case NATIVE_PARAM_USE_NATIVE_BUFFER
:
346 /* private buffers are allocated */
349 case NATIVE_PARAM_PRESERVE_BUFFER
:
350 case NATIVE_PARAM_MAX_SWAP_INTERVAL
:
360 gdi_display_destroy(struct native_display
*ndpy
)
362 struct gdi_display
*gdpy
= gdi_display(ndpy
);
367 gdpy
->base
.screen
->destroy(gdpy
->base
.screen
);
372 static struct native_display
*
373 gdi_create_display(HDC hDC
, struct native_event_handler
*event_handler
,
376 struct gdi_display
*gdpy
;
377 struct sw_winsys
*winsys
;
379 gdpy
= CALLOC_STRUCT(gdi_display
);
384 gdpy
->event_handler
= event_handler
;
385 gdpy
->base
.user_data
= user_data
;
387 winsys
= gdi_create_sw_winsys();
393 gdpy
->base
.screen
= gdpy
->event_handler
->new_sw_screen(&gdpy
->base
, winsys
);
394 if (!gdpy
->base
.screen
) {
396 winsys
->destroy(winsys
);
401 gdpy
->base
.destroy
= gdi_display_destroy
;
402 gdpy
->base
.get_param
= gdi_display_get_param
;
404 gdpy
->base
.get_configs
= gdi_display_get_configs
;
405 gdpy
->base
.create_window_surface
= gdi_display_create_window_surface
;
410 static struct native_display
*
411 native_create_display(void *dpy
, struct native_event_handler
*event_handler
,
414 return gdi_create_display((HDC
) dpy
, event_handler
, user_data
);
417 static const struct native_platform gdi_platform
= {
419 native_create_display
422 const struct native_platform
*
423 native_get_gdi_platform(void)
425 return &gdi_platform
;